/** Progetto PRAISED **/
package it.uniroma3.dia.praised.brenda.parser;

import it.uniroma3.dia.praised.brenda.validator.Validator;
import it.uniroma3.dia.praised.exception.CrawlerException;
import it.uniroma3.dia.praised.exception.MainException;
import it.uniroma3.dia.praised.factory.XmlReaderFactory;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.sax.SAXSource;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
import org.xml.sax.XMLReader;

/**
 * ParserBrenda: Classe che estrae dalla root del sito web BRENDA l'insieme dei link che saranno analizzati 
 * successivamente nel processo di crawling
 * 
 * @author Accosta Augusto
 * @author Lopez Elisabetta
 * 
 * @see it.uniroma3.dia.praised.brenda.validator.Validator
 * @see it.uniroma3.dia.praised.factory.XmlReaderFactory
 * @version 1.0
 * 
 */
public class ParserBrenda {
	
	private XMLReader reader;
	
	/**
	 * Costruttore di default che effettua le inizializzazioni delle variabili di classe
	 * @throws CrawlerException 
	 */
	public ParserBrenda() throws MainException {
		
		try {
			this.reader = XmlReaderFactory.newXmlReader();
		} catch (SAXNotRecognizedException e) {
			throw new MainException(e.getMessage());
		} catch (SAXNotSupportedException e) {
			throw new MainException(e.getMessage());
		}
	}
	
	/**
	 * Metodo che recupera l'elenco dei link presenti all'interno di una pagina web 
	 * 
	 * @param root - Url della radice del sito
	 * @return listaURL - Set di link estratti
	 */
	public List<URL> getHref(URL root) throws MainException {
		
		try {
			/* Ricostruzione del DOM relativo alla pagina di interesse */
			Transformer transformer = TransformerFactory.newInstance().newTransformer();
			DOMResult result = new DOMResult();
			transformer.transform(new SAXSource(reader, new InputSource(root.openStream())), result);
			
			/* Esecuzione dell'espressione xpath che recupera tutte le ancore della pagina */
			XPathFactory factory = XPathFactory.newInstance();
			XPath xPath = factory.newXPath();
			String pattern = "//a";
			NodeList ancore = (NodeList) xPath.evaluate(pattern, result.getNode(), XPathConstants.NODESET);
						
			/* Recupero dell link incluso nell'attributo href di ogni ancora*/
			List<URL> listaURL = new ArrayList<URL>(ancore.getLength());
			for (int i=0; i < ancore.getLength(); i++) {
				/* Costruzione statica del link appena estratto per formare un URL assoluto */
				URL urlEnzima = Validator.buildURL(root, ancore.item(i).getAttributes().getNamedItem("href").getNodeValue());
				if (urlEnzima.toString().contains("ecno")) // Filtro solo i link che mi servono
					listaURL.add(urlEnzima);
			} 
			return listaURL;
		  
		} catch (MalformedURLException e) {
			throw new MainException(e.getMessage());
		} catch (TransformerConfigurationException e) {
			throw new MainException(e.getMessage());
		} catch (TransformerFactoryConfigurationError e) {
			throw new MainException(e.getMessage());
		} catch (TransformerException e) {
			throw new MainException(e.getMessage());
		} catch (IOException e) {
			throw new MainException(e.getMessage());
		} catch (XPathExpressionException e) {
			throw new MainException(e.getMessage());
		} catch (Exception e) {
			throw new MainException(e.getMessage());
		}

	}
	
}
